<?php
/*------------------------------------------------------------------------------
Django templating syntax implemation library, object-oriented

Copyright (C) 2006 J.Ducastel <jducastel@jducastel.fr>

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
------------------------------------------------------------------------------*/

/**
*
* @author J.Ducastel <jducastel@jducastel.fr>
* @version 
*/
class djangoTpl {
/*------------------------------------------------------------------------------
                                                                     constructor
------------------------------------------------------------------------------*/
	/**
	*
	* @access
	*/
	function djangoTpl(&$str,$id=null) {
		$this->__construct($str);
	}/**/
	
	/**
	* "real" constructor
	* @access public
	*/
	function __construct(&$str) {
		// including tags and filters
		$path=dirname(__FILE__).'/'; //echo "<p>$path</p>";
		include_once($path.'djangotpl-tags.lib.php');
		include_once($path.'djangotpl-filters.lib.php');
		$this->_buildFromString($str);
	}/**/
/*------------------------------------------------------------------------------
                                                                  public methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access public
	* @return 
	*/
	function render($data=null) {
		// building context
		$context=&new djangoTplContext($data);
		// rendering
		$rendered='';
		// looping nodes
		for ($n=0; $n<count($this->nodes); $n++)
			$rendered.=$this->nodes[$n]->render($context);
		return $rendered;
	}/**/
	

	
	/**
	* 
	* @param
	* @access public
	* @return 
	* /
	function () {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                      properties
------------------------------------------------------------------------------*/
	/**
	* @var array djangoTplNode
	*/
	var $nodes=array();
	// var $regex_
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
	/**
	* builds internal tree from string
	* @param string $str
	* @access private
	* @return bool
	*/
	function _buildFromString(&$str) {
		// spliting into tokens
		//$regex='/({%[^{}]+%})/';
		//$tokens=preg_split($this->regex_tokenspliter,$str,-1,PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
		$tokens=djangoTplParser::tokenize($str);
		//echo wakdebug::vardump($tokens);
		while ($node=&djangoTplParser::tokensToNode($tokens)) {
			$this->nodes[]=&$node;
		}
		return true;
	}/**/
	
	/**
	* 
	* @param
	* @access private
	* @return 
	* /
	function () {
		
	}/**/
}

/**
*
* @static
* @author J.Ducastel <jducastel@jducastel.fr>
* @version 
*/
class djangoTplParser {
/*------------------------------------------------------------------------------
                                                                     constructor
------------------------------------------------------------------------------*/
	/**
	*
	* @access
	* /
	function () {
		$this->__construct();
	}/**/
	
	/**
	* real constructor
	* @access
	* /
	function __construct() {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                  public methods
------------------------------------------------------------------------------*/
	/**
	* splits string into tokens
	* @param
	* @access public
	* @return array
	*/
	function tokenize(&$str) {
		$regex='/({%[^{}]+%})|({{[^{}]+}})/';
		$tokens=preg_split($regex,$str,-1,PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
		for ($n=0; $n<count($tokens); $n++) {
			$tokens[$n]=&new djangoTplToken($tokens[$n]);
		}
		return $tokens;
	}/**/
	
	/**
	* Builds next node from tokens array
	* @static
	* @param array &$tokens
	* @access public
	* @return djangoTplNode
	*/
	function & tokensToNode(&$tokens) {
		// infinite loop protection
		static $ifni;
		$ifni++;
		if ($ifni>1000) {
			trigger_error("infinite loop ?");
			exit;
		}
		// preparing to build node
		$node=false;
		// checking next token
		if (!$token=array_shift($tokens) or !is_a($token,'djangoTplToken'))
			return $node;
		// building upon token type
		switch ($token->getType()) {
			case 'text':
				$node=new djangoTplTextNode();
				$node->buildFromTokens($token);
				break;
			case 'var':
				$node=new djangoTplVarNode();
				$node->buildFromTokens($token);
				break;
			case 'tag':
				// is tag registered ?
				$tag=$token->getTagName();
				$class=djangoTplParser::getTagNodeClass($tag);
				//$registered_tags=djangoTplParser::tags();
				if (class_exists($class)) {
					// building appropriate node
					$node=&new $class();
					$node->buildFromTokens($token,$tokens);
					break;
				}
				// unknown/unsupported tag, defaulting
				$node=&new djangoTplTagNode();
				$node->buildFromTokens($token,$tokens);
				break;
			default:
				break;
		}
		return $node;
	}/**/
	
	/**
	* keeps list of registered tags
	* @static
	* @param string $newtag
	* @access public
	* @return array
	* /
	function tags($newtag=null) {
		//$classes=get_declared_classes();
		//$tags
		//echo wakdebug::vardump($classes);
		static $tags=array();
		$class=djangoTplParser::getTagNodeClass($newtag);
		if (is_string($newtag) and class_exists($class))
			$tags[]=$newtag;
		return $tags;
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return 
	*/
	function getTagNodeClass($tag) {
		return 'djangotpltagnode_'.$tag;
	}/**/
	
	/**
	* build nodes from tokens until it reaches defined ending tag
	* @param array &$tokens djangoTplToken
	* @param string $closingTag may accept several closing tags, separated by space
	* @access public
	* @return array djangoTplNode
	*/
	function tokensToNodesUntilTag(&$tokens,$endtagsdef='end') {
		$n=0; $nodes=array();
		$endtags=explode(' ',$endtagsdef);
		while ($node=&djangoTplParser::tokensToNode($tokens)) {
			// infinite loop protection
			$n++; if ($n>500) break;
			// is node expected end tag ?
			if ($node->isTag() and in_array($node->getTagName(),$endtags)) {
				// reached closing tag
				// echo '<p>reached '.$endtag.'</p>';
				//return true;
				break;
			}
			$nodes[]=&$node;
			
		}
		return $nodes;
	}/**/
	
	/**
	* apply filter to value, or return value if failed
	* @param mixed $value
	* @param string $filter filter definition
	* @access public
	* @return mixed
	*/
	function applyFilter($value,$filter) {
		// parsing filter
		if (!ereg('^([^:]*)(:"(.*)")?$',$filter,$search)) {
			trigger_error("invalid filter $filter");
			return $value;
		}
		//echo wakdebug::vardump($search);
		$filterFunc=$search[1];
		$filterArg=$search[3];
		// searching for function
		if (function_exists('djangotplfilter_'.$filterFunc)) {
			// using custom djangotpl filter func
			$func='djangotplfilter_'.$filterFunc;
		} else if (function_exists($filterFunc)) {
			// backing to php native func
			$func=$filterFunc;
		} else {
			// no function found
			trigger_error("no function found for $filterFunc");
			return $value;
		}
		// function call with or without arg
		if ($filterArg) {
			$value=$func($value,$filterArg);
		} else {
			$value=$func($value);
		}
		return $value;
	}/**/
	
	/**
	* evals expression and return value
	* expression may be path, quoted string
	* @param djangoTplContext &$context
	* @param string $expr expression to eval
	* @access public
	* @return mixed
	*/
	function evalExpression(&$context,$expr) {
		//echo "<p>djangoTplParser::evalExpression($expr)</p>";
		$value=null;
		// is quoted string ?
		if (ereg('^"(.*)"$',$expr,$search))
			return $search[1];
		// is integer ?
		if (ereg('^[0-9]+$',$expr))
			return intval($value);
		// is constant
		if (defined($expr))
			return constant($expr);
		// is var
		$value=$context->getpath($expr);
		if (!is_null($value))
			return $value;
		// echo wakdebug::vardump($value);
		//echo "<p>no value for $expr !</p>";
		return $value;
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return 
	* /
	function () {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                      properties
------------------------------------------------------------------------------*/
	/**
	* @var type desc
	*/
	//var //
	
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access protected
	* @return 
	* /
	function () {
		
	}/**/
	
	/**
	* 
	* @param
	* @access protected
	* @return 
	* /
	function () {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access private
	* @return 
	* /
	function () {
		
	}/**/
	
	/**
	* 
	* @param
	* @access private
	* @return 
	* /
	function () {
		
	}/**/
}

/**
*
* @author J.Ducastel <jducastel@jducastel.fr>
* @version 
*/
class djangoTplToken {
/*------------------------------------------------------------------------------
                                                                     constructor
------------------------------------------------------------------------------*/
	/**
	* constructor
	* @access public
	*/
	function djangoTplToken(&$str) {
		$this->str=&$str;
		//$this->__construct();
		if (substr($str,0,2)=='{{') {
			$this->setAsVar();
		} else if (substr($str,0,2)=='{%') {
			$this->setAsTag();
		} else {
			$this->type='text';
		}
	}/**/
	
	/**
	* real constructor
	* @access
	* /
	function __construct() {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                  public methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access public
	* @return 
	*/
	function getType() {
		return $this->type;
	}/**/
	
	/**
	* is the token a tag token ?
	* @access public
	* @return bool
	*/
	function isTag() {
		return $this->type=='tag';
	}/**/
	
	/**
	* is the token a var token ?
	* @access public
	* @return bool
	*/
	function isVar() {
		return $this->type=='var';
	}/**/
	
	/**
	* is the token a text token ?
	* @access public
	* @return bool
	*/
	function isText() {
		return $this->type=='text';
	}/**/
	
	/**
	* return tag name if relevant
	* @param
	* @access public
	* @return false|string
	*/
	function getTagName() {
		if ($this->getType()!='tag')
			return false;
		return $this->tagname;
	}/**/
	
	/**
	* return tag definition if relevant
	* @access public
	* @return string
	*/
	function getTagDef() {
		if ($this->getType()!='tag')
			return false;
		return $this->tagdef;
	}/**/
	
	/**
	* return var name if relevant
	* @access public
	* @return string
	*/
	function getVarName() {
		if ($this->getType()!='var')
			return false;
		return $this->varname;
	}/**/
	
	/**
	* return var filters if relevant
	* @access public
	* @return array
	*/
	function getVarFilters() {
		if ($this->getType()!='var')
			return false;
		return $this->filters;
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return 
	* /
	function () {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                      properties
------------------------------------------------------------------------------*/
	/**
	* @var string text|var|tag|invalid
	*/
	var $type='invalid'; 
	/**
	* @var string content
	*/
	var $str='';
	//var $tagname;
	//var $tagdef;
	//var 
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access protected
	* @return 
	* /
	function () {
		
	}/**/
	
	/**
	* 
	* @param
	* @access protected
	* @return 
	* /
	function () {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access private
	* @return bool
	*/
	function setAsTag() {
		if (!ereg('^\{% ?([a-zA-Z]+) ?(.*) ?%\}$',$this->str,$search)) {
			$this->type='invalid';
			return false;
		}
		$this->tagname=trim($search[1]);
		$this->tagdef=trim($search[2]);
		$this->type='tag';
		return true;
	}/**/
	
	/**
	* parse token string and sets token as var
	* @access private
	* @return bool
	*/
	function setAsVar() {
		// extracting definition from 
		if (!ereg('^\{\{ ?([^{}]+) ?\}\}$',$this->str,$search)) {
			$this->type='invalid';
			return false;
		}
		$def=trim($search[1]);
		$parts=explode('|',$def);
		// first part is var name
		$this->varname=array_shift($parts);
		// all aother parts are filters
		$this->filters=$parts;
		$this->type='var';
		return true;
	}/**/
}

/**
*
* @use datapath
* @author J.Ducastel <jducastel@jducastel.fr>
* @version 
*/
class djangoTplContext {
/*------------------------------------------------------------------------------
                                                                     constructor
------------------------------------------------------------------------------*/
	/**
	*
	* @access
	*/
	function djangoTplContext(&$data) {
		$this->__construct($data);
	}/**/
	
	/**
	* real constructor
	* @access
	*/
	function __construct(&$data) {
		$this->setDataSource($data);
	}/**/
/*------------------------------------------------------------------------------
                                                                  public methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access public
	* @return bool
	*/
	function setDataSource(&$data) {
		$this->data=&$data;
		return true;
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return 
	*/
	function getPath($path) {
		return datapath::get($this->data,$path);
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return 
	* /
	function loop($path) {
		static $looping
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return 
	*/
	function setPathAlias($path, $alias) {
		//echo "<p>setting $alias as alias for $path</p>";
		$target=&datapath::get($this->data,$path);
		datapath::setRef($this->data,$target,$alias);
		//echo wakdebug::vardump($this->data);
	}/**/
	
	/**
	* return children keys at a path
	* @param string $path
	* @access public
	* @return array
	*/
	function getKeys($path) {
		return datapath::getChildKeys($this->data,$path);
	}/**/
	
	/**
	* Sets value for a path
	* @param string $path
	* @param mixed value
	* @access public
	* @return bool
	*/
	function setPath($path,$value) {
		return datapath::set($this->data,$value,$path);
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return 
	* /
	function () {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                      properties
------------------------------------------------------------------------------*/
	/**
	* @var type desc
	*/
	var $data; // data source reference
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access protected
	* @return 
	* /
	function () {
		
	}/**/
	
	/**
	* 
	* @param
	* @access protected
	* @return 
	* /
	function () {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access private
	* @return 
	* /
	function () {
		
	}/**/
	
	/**
	* 
	* @param
	* @access private
	* @return 
	* /
	function () {
		
	}/**/
}

/**
* generic node class
* mostly static use, except for djangoTpl root node
* @author J.Ducastel <jducastel@jducastel.fr>
* @version 
*/
class djangoTplNode {
/*------------------------------------------------------------------------------
                                                                     constructor
------------------------------------------------------------------------------*/
	/**
	*
	* @access
	* /
	function () {
		$this->__construct();
	}/**/
	
	/**
	* real constructor
	* @access
	* /
	function __construct() {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                  public methods
------------------------------------------------------------------------------*/
	/**
	* builds itself from tokens array
	* @param djangoTplToken &$selfToken
	* @param array &$nextTokens djangoTplToken
	* @access public
	* @return bool
	*/
	function buildFromTokens(&$selfToken, &$nextTokens) {
		//$this->token=&$selfToken;
		return true;
	}/**/

	/**
	* default rendering method
	* @param djangoTplContext &$context
	* @access public
	* @return string
	*/
	function render(&$context) {
		
		if (!$this->isAtomic())
			return $this->renderChildNodes();
		
		return '';
	}/**/
	
	/**
	* is the node atomic (has no children)
	* @access public
	* @return bool
	*/
	function isAtomic() {
		return true;
	}/**/
	
	/**
	* is a tag node ?
	* @access public
	* @return bool
	*/
	function isTag() {
		return is_a($this,'djangoTplTagNode');
	}/**/
	
	/**
	* is a var node
	* @param
	* @access public
	* @return bool
	*/
	function isVar() {
		return is_a($this,'djangoTplVarNode');
	}/**/
	
	/**
	* is a text node ?
	* @param
	* @access public
	* @return bool
	*/
	function isText() {
		return is_a($this,'djangoTplTextNode');
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return 
	* /
	function () {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                      properties
------------------------------------------------------------------------------*/
	/**
	* @var type desc
	*/
	//var $is_atomic=true;
	// var $childnodes=array();
	
	/**
	*
	*/
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/

	
	/**
	* render child nodes
	* @param djangoTplContext
	* @access protected
	* @return string
	*/
	function renderChildNodes(&$context) {
		$rendered='';
		for ($n=0; $n<count($this->childnodes); $n++)
			$rendered.=$this->childnodes[$n]->render($context);
		return $rendered;
	}/**/
	
	/**
	* renders child nodes before a defined tag node
	* @param djangoTplContext &$context
	* @param string $tag tag name
	* @access protected
	* @return string
	*/
	function renderChildNodesBeforeTag(&$context, $tag) {
		$rendered='';
		for ($n=0; $n<count($this->childnodes); $n++) {
			$node=&$this->childnodes[$n];
			if ($node->isTag() and $node->getTagName()==$tag)
				break;
			$rendered.=$node->render($context);
		}
		return $rendered;
	}/**/
	
	/**
	* renders child nodes after a defined tag node
	* @param djangoTplContext &$context
	* @param string $tag tag name
	* @access protected
	* @return string
	*/
	function renderChildNodesAfterTag(&$context, $tag) {
		$rendered=''; $found=false;
		for ($n=0; $n<count($this->childnodes); $n++) {
			$node=&$this->childnodes[$n];
			if ($found)
				$rendered.=$node->render($context);
			if ($node->isTag() and $node->getTagName()==$tag)
				$found=true;
		}
		return $rendered;
	}/**/
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access private
	* @return 
	* /
	function () {
		
	}/**/
	
	/**
	* 
	* @param
	* @access private
	* @return 
	* /
	function () {
		
	}/**/
}

/**
* 
* @static
* @author J.Ducastel <jducastel@jducastel.fr>
* @version 
*/
class djangoTplTextNode extends djangoTplNode {
/*------------------------------------------------------------------------------
                                                                     constructor
------------------------------------------------------------------------------*/
	/**
	*
	* @access
	* /
	function djangoTplTextNode(&$text) {
		$this->__construct($text);
	}/**/
	
	/**
	* real constructor
	* @access private
	* /
	function __construct(&$text) {
		$this->text=&$text;
	}/**/
/*------------------------------------------------------------------------------
                                                                  public methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @static
	* @param
	* @access public
	* @return 
	*/
	function render() {
		return $this->text;
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return bool
	*/
	function buildFromTokens($selfToken) {
		$this->text=$selfToken->str;
		return true;
	}/**/
/*------------------------------------------------------------------------------
                                                                      properties
------------------------------------------------------------------------------*/
	/**
	* @var type desc
	*/
	// var //
	
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access protected
	* @return 
	* /
	function () {
		
	}/**/
	
	/**
	* 
	* @param
	* @access protected
	* @return 
	* /
	function () {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access private
	* @return 
	* /
	function () {
		
	}/**/
	
	/**
	* 
	* @param
	* @access private
	* @return 
	* /
	function () {
		
	}/**/
}



/**
*
* @author J.Ducastel <jducastel@jducastel.fr>
* @version 
*/
class djangoTplVarNode extends djangoTplNode {
/*------------------------------------------------------------------------------
                                                                     constructor
------------------------------------------------------------------------------*/
	/**
	*
	* @access
	* /
	function () {
		$this->__construct();
	}/**/
	
	/**
	* real constructor
	* @access
	* /
	function __construct() {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                  public methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access public
	* @return bool
	*/
	function buildFromTokens($selfToken/*, &$nextTokens*/) {
		// $this->token=&$selfToken;
		$this->path=$selfToken->getVarName();
		//echo wakdebug::vardump($selfToken);
		$this->filters=$selfToken->getVarFilters();
		return true;
	}/**/
	
	/**
	* Redners as string
	* @param &$context
	* @access public
	* @return string
	*/
	function render(&$context) {
		// getting value
		$value=djangoTPlParser::evalExpression($context,$this->path);
		//echo $value;
		if ($value===null) {
			//trigger_error("no value for {$this->path}");
			return '';
		}
		// applying filters
		foreach ($this->filters as $filter)
			$value=djangoTplParser::applyFilter($value,$filter);
		// returning formatted value
		return strval($value);
		//return '<!-- var: '.$this->token->varname.' -->';
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return 
	* /
	function () {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                      properties
------------------------------------------------------------------------------*/
	/**
	* @var type desc
	*/
	//var //
	
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access protected
	* @return 
	* /
	function () {
		
	}/**/
	
	/**
	* 
	* @param
	* @access protected
	* @return 
	* /
	function () {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access private
	* @return 
	* /
	function () {
		
	}/**/
	
	/**
	* 
	* @param
	* @access private
	* @return 
	* /
	function () {
		
	}/**/
}

/**
* generic node tag
* use only static methods, unless tag is undefined
* @author J.Ducastel <jducastel@jducastel.fr>
* @version 
*/
class djangoTplTagNode extends djangoTplNode {
/*------------------------------------------------------------------------------
                                                                     constructor
------------------------------------------------------------------------------*/
	/**
	*
	* @access
	* /
	function () {
		$this->__construct();
	}/**/
	
	/**
	* real constructor
	* @access
	* /
	function __construct() {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                  public methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access public
	* @return 
	*/
	function render(&$context) {
		return '<!-- unsupported tag : '.$this->getTagName().' -->'
		.($this->isAtomic()?'':
			$this->renderChildNodes($context));
	}/**/
	
	/**
	* builds itself from tokens
	* @param djangoTplToken &$selfToken
	* @param array &$nextTokens djangoTplToken
	* @access public
	* @return bool
	*/
	function buildFromTokens(&$selfToken, &$nextTokens) {
		//$this->token=&$selfToken;
		$this->tagname=$selfToken->getTagName();
		$this->tagdef=$selfToken->getTagDef();
		// building child nodes
		$this->buildChildNodesFromTokens($nextTokens);
		return true;
	}/**/
	
	/**
	* return own tag name
	* @param
	* @access public
	* @return string
	*/
	function getTagName() {
		return $this->tagname;
		// class name minus 'djangoTplTagNode_''
		//$tagname=substr(get_class($this),17); echo " [$tagname] ";
		return $tagname;
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return 
	* /
	function () {
		
	}/**/
	
	/**
	* 
	* @param
	* @access public
	* @return 
	* /
	function () {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                      properties
------------------------------------------------------------------------------*/
	/**
	* @var type desc
	*/
	var $tagname;
	
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
	/**
	* loops tokens array until ending tag, build child nodes
	* 
	* @param array &$tokens
	* @access protected
	* @return bool
	*/
	function buildChildNodesFromTokens(&$tokens) {
		//echo $this->getTagName().' building child nodes<br />';
		if ($this->isAtomic())
			return false;
		// expected end tag name ?
		$endtag='end'.$this->getTagName();
		// looping
		$this->childnodes=djangoTplParser::tokensToNodesUntilTag($tokens,$endtag);
		return true;
	}/**/
	
	/**
	* 
	* @param
	* @access protected
	* @return 
	* /
	function () {
		
	}/**/
/*------------------------------------------------------------------------------
                                                                 private methods
------------------------------------------------------------------------------*/
	/**
	* 
	* @param
	* @access private
	* @return 
	* /
	function () {
		
	}/**/
	
	/**
	* 
	* @param
	* @access private
	* @return 
	* /
	function () {
		
	}/**/
}
?>
